<!DOCTYPE html>
<html>
    <head>

        <link rel="canonical" href="http://www.jointjs.com/" />
        <meta name="description" content="Create interactive diagrams in JavaScript easily. JointJS plugins for ERD, Org chart, FSA, UML, PN, DEVS, LDM diagrams are ready to use." />
        <meta name="keywords" content="JointJS, JavaScript, diagrams, diagramming library, UML, charts" />

        <link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700" rel="stylesheet" type="text/css" />
        <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">

        <link rel="stylesheet" href="css/tutorial.css" />
        <link rel="stylesheet" href="../node_modules/prismjs/themes/prism.css">


        <!-- Dependencies: -->
        <script src="../node_modules/jquery/dist/jquery.js"></script>
        <script src="../node_modules/lodash/lodash.js"></script>
        <script src="../node_modules/backbone/backbone.js"></script>


        <link rel="stylesheet" type="text/css" href="../build/joint.min.css" />
        <script type="text/javascript" src="../build/joint.min.js"></script>

        <title>JointJS - JavaScript diagramming library - Getting started.</title>

    </head>
    <body class="language-javascript tutorial-page">

        <script>
            SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function (toElement) {
                return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
            };
        </script>

        <div id="constraint-move-to-circle" class="tutorial">

            <h2>Constraint movement to circle/ellipse/rectangle</h2>

            <p>Some applications might need to constrain an element dragging to ellipse, circle or even rectangle
                shapes.
                This post shows you how this can be achieved via a custom view for your element and with the help of the
                handy geometry library
                that is part of JointJS.
            </p>

            <div id="paper-constraint-move-to-circle"></div>

            <h3>Creating a custom constraint view</h3>

            <p>First we need to create a custom view that overrides the <code>pointerdown()</code> and
                <code>pointermove()</code> methods. These methods make sure that the <code>x</code> and <code>y</code>
                coordinates passed to the default <code>pointerdown()</code> and <code>pointermove()</code>
                methods are located on the boundary of our ellipse object. To compute the points on the boundary
                of our ellipse, we simply take advantage of the <code>ellipse.prototype.intersectionWithLineFromCenterToPoint()</code>
                function. [A complete documentation to the geometry library of JointJS can be found on
                <a href="http://www.daviddurman.com/hidden-gold-of-jointjs-the-geometry-library.html" target="_blank">my blog</a>]
            </p>

            <pre><code>// This is the ellipse that will be used as a constraint for our element dragging.
var constraint = g.ellipse(g.point(200, 150), 100, 80);

var ConstraintElementView = joint.dia.ElementView.extend({

    pointerdown: function(evt, x, y) {
        var position = this.model.get('position');
        var size = this.model.get('size');
        var center = g.rect(position.x, position.y, size.width, size.height).center();
        var intersection = constraint.intersectionWithLineFromCenterToPoint(center);
        joint.dia.ElementView.prototype.pointerdown.apply(this, [evt, intersection.x, intersection.y]);
    },
    pointermove: function(evt, x, y) {
        var intersection = constraint.intersectionWithLineFromCenterToPoint(g.point(x, y));
        joint.dia.ElementView.prototype.pointermove.apply(this, [evt, intersection.x, intersection.y]);
    }
});</code></pre>

            <h3>Creating a paper and forcing it to use our custom view</h3>

            <p>Now we can just create a graph and paper as usual and tell the paper to use
                our custom view for all the element models. [Note that if you need a custom view
                for just one type of model (not all the models added to the paper), you can do that
                be defining a view for a specific type. An example of this can be found in the
                <a href="https://groups.google.com/forum/#!topic/jointjs/TigaktJ4wFM" target="_blank">forum page</a>.]</p>

            <pre><code>var graph = new joint.dia.Graph;

var paper = new joint.dia.Paper({
    el: $('#paper'),
    width: 650,
    height: 400,
    gridSize: 1,
    model: graph,
    elementView: ConstraintElementView
});</code></pre>

            <h3>Finalizing the example by adding elements to the graph and drawing our constraint ellipse</h3>

            <p>We're almost there! Now we just add a circle element to the paper which will be the one
                whose dragging we just constraint. We also draw our ellipse so that it is visible in the paper.
                Here we'll use the built-in Vectorizer library that makes life easier when dealing with SVG.
            </p>

            <pre><code>var earth = new joint.shapes.basic.Circle({
    position: constraint.intersectionWithLineFromCenterToPoint(g.point(100, 100)).offset(-10, -10),
    size: { width: 20, height: 20 },
    attrs: { text: { text: 'earth' }, circle: { fill: '#2ECC71' } },
    name: 'earth'
});
graph.addCell(earth);

var orbit = V('&lt;ellipse/&gt;');
orbit.attr({
    cx: constraint.x, cy: constraint.y, rx: constraint.a, ry: constraint.b
});
V(paper.viewport).append(orbit);</code></pre>

            <p>That's it! One can use the exact same technique to constrain dragging to a rectangular area.
                The full source code to the demo is available here:</p>
            <a href="js/circle-constraint.js">circle-constraint.js</a>

            <script type="text/javascript" src="js/circle-constraint.js"></script>

        </div>

        <script src="../node_modules/prismjs/prism.js"></script>

    </body>
</html>
